﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DwarfConfigurator
{   
    /// <summary>
    /// Presentation of Hidden Markov model.
    /// </summary>
    public class HMM
    {
        /// <summary>
        /// Number of states;  Q = {1,2,...,N} .
        /// </summary>
        private int numberOfStates;

        /// <summary>
        /// Number of observation symbols; V={1,2,...,M}.
        /// </summary>
        private int numberOfObservationSymbols;

        /// <summary>
        /// A[1..N][1..N]. a[i][j] is the transition prob
        /// of going from state i at time t to state j
        /// at time t+1.
        /// </summary>
        public double[][] stateTransitionMatrix;

        /// <summary>
        /// B[1..N][1..M] is the  probability 
        /// of observing symbol j in state i .
        /// </summary>
        public double[][] observationProbabilityMatrix;
        /// <summary>
        /// [1..numberOfStates]  Is the initial state distribution.
        /// </summary>
        public double[] initialStates;

        public HMM(int n, int m)
        {
            numberOfStates = n;
            numberOfObservationSymbols = m;
            //creation of  state transition and observation matrices
            stateTransitionMatrix = new double[numberOfStates][];
            observationProbabilityMatrix = new double[numberOfStates][];
            for (int i = 0; i < numberOfStates; i++)
            {
                stateTransitionMatrix[i] = new double[numberOfStates];
                observationProbabilityMatrix[i] = new double[numberOfObservationSymbols];
            }

            initialStates = new double[numberOfStates];
        }

        public int getNumberOfStates()
        {
            return numberOfStates;
        }
        public int getNumberOfObservation()
        {
            return numberOfObservationSymbols;
        }
    }

    /// <summary>
    /// Presentation of Viterbi model.
    /// </summary>
    public class ViterbiModel
    {
        /// <summary>
        /// Length of observation the sequence.
        /// </summary>
        private int lengthOfObservationSequence;
        /// <summary>
        /// Maximization of probability.
        /// </summary>
        private double probability;

        /// <summary>
        /// Is the best score(highest probability) along a single path,at time t.
        /// </summary>
        public double[][] delta;

        /// <summary>
        /// Track of the argument which maximized.
        /// </summary>
        public int[][] psi;

        /// <summary>
        /// Observation sequence [ O ].
        /// </summary>
        public int[] observationSequence;

        /// <summary>
        /// Sequence of state [ Q ].
        /// </summary>
        public int[] sequenceOfState;

        public ViterbiModel(int t, HMM hmm)
        {
            lengthOfObservationSequence = t;
            //creation of delta and psi work elements
            delta = new double[lengthOfObservationSequence][];
            psi = new int[lengthOfObservationSequence][];
            int numberOfState = hmm.getNumberOfStates();
            for (int i = 0; i < lengthOfObservationSequence; i++)
            {
                delta[i] = new double[numberOfState];
                psi[i] = new int[numberOfState];
            }

            observationSequence = new int[lengthOfObservationSequence];
            sequenceOfState = new int[lengthOfObservationSequence];
        }

        public int getLengthOfObservationSequence()
        {
            return lengthOfObservationSequence;
        }
        public double getProbability()
        {
            return probability;
        }
        public void setProbability(double p)
        {
            probability = p;
        }
    }


    public class DataModel
    {
        /// <summary>
        /// Short dwarf's description.
        /// </summary>
        public String DWARF_NAME;

        /// <summary>
        /// Constants for output files's names
        /// </summary>
        public String DWARF_NAME_OUTPUT;

        public int[] arrayOflengthForProc;

        public const int ROOT_PROCESS = 0;
        /// <summary>
        /// True for master process.
        /// </summary>
        public bool isRootThread = false;

        /// <summary>
        /// Loading of process.
        /// </summary>
        public int lengthForProc;

        public int startIndx;
        public int endIndx;

        /// <summary>
        /// Instance of Hidden Markov model.
        /// </summary>
        public HMM hmm;

        /// <summary>
        /// Instance of Viterbi model.
        /// </summary>
        public ViterbiModel vit;

        /// <summary>
        /// Initializing for non master processors.
        /// </summary>
        public void init(int n, int m, int t)
        {
            hmm = new HMM(n, m);                   //creation of Hidden Markov model  instance
            vit = new ViterbiModel(t, this.hmm);   //creation of Viterbi Model instance
        }
    }
}
